// Classic/Functional OOP

function Student(name) { // Constructor === OOP Class (Function constructor)
	
}

var st = new Student('Петър'); // instance of Person
console.log(st); // {}
console.log(st instanceof Student); // true

var stF = Student();
console.log(stF); // undefined
console.log(stF instanceof Student); // false

String.prototype.repeat = function (count) {
    var resul;
    result = '';

    for (var i = 0; i < count; i++) {
        result += this;
    }
};

console.prototype.log = function(text) {
    console.warn(message);
};

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.sayHello = function () {  // неправилен начин за закачане на метод, защото за всеки обект се създава по една функция
        return 'Hello! Said ' + this.name; // може и без this, но ще вземе параметъра, а това е Closure
    };
}

var person1 = new Person('Мария', 7);
var person2 = new Person('Петър', 11);
console.log(person1.name);
console.log(person2.name);
console.log(person1.sayHello === person2.sayHello); // false

var arr1 = [];
var arr2 = [];
console.log(arr1.slice === arr2.slice); // true (чрез prototype)

function Animal(name, age) {
    var _name = name;
    var _age = age;
}
Animal.prototype.enjoy = function () { _name = 'me' }; // closure

var CONSTANT = {}; // обект с константи

// При класик имаме скрити данни, при прототипното имаме бързодействие

var animal = new Animal('име', 'възраст');
console.log(animal.enjoy());

var animalEnjoy = animal.enjoy;

// this е това, което го извиква, т.е. в global scope ще е undefined

function Constructor(params) {
    name = params.name || DEFAULT_NAME_VALUE;

    if (!(this instanceof arguments.callee)) {
        return new Constructor(params);
    }
}

var Machine = (function () {
    var STUDENT_CONSTANTS = {
        MAX_GRADE: 12,
        MIN_GRADE: 1
    };

    function Machine(name, type) {

    }

    Machine.prototype.disappear = function () {};

    return Machine;
});

throw 'Error message'; // хвърляне на грешка

var fakeStudent = {
    _name: 'Fake',
    _grade: 0
};

Student.prototype.introduce.call(fakeStudent);

Student.passExam = function () {}; // static method